{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Process STDOUT and STDERR is being redirected to /tmp/raylogs/.\n",
      "Waiting for redis server at 127.0.0.1:59613 to respond...\n",
      "Waiting for redis server at 127.0.0.1:33812 to respond...\n",
      "Starting local scheduler with the following resources: {'CPU': 8, 'GPU': 1}.\n",
      "\n",
      "======================================================================\n",
      "View the web UI at http://localhost:8889/notebooks/ray_ui8932.ipynb?token=dc080f33528030d862127ce4e666155206eec167c991183c\n",
      "======================================================================\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'node_ip_address': '192.168.0.12',\n",
       " 'redis_address': '192.168.0.12:59613',\n",
       " 'object_store_addresses': [ObjectStoreAddress(name='/tmp/plasma_store31436194', manager_name='/tmp/plasma_manager37448059', manager_port=36155)],\n",
       " 'local_scheduler_socket_names': ['/tmp/scheduler98387521'],\n",
       " 'raylet_socket_names': [],\n",
       " 'webui_url': 'http://localhost:8889/notebooks/ray_ui8932.ipynb?token=dc080f33528030d862127ce4e666155206eec167c991183c'}"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from fractalai.model import RandomDiscreteModel\n",
    "from fractalai.environment import ParallelEnvironment, AtariEnvironment\n",
    "from fractalai.swarm_wave import SwarmWave\n",
    "from fractalai.fractalmc import FractalMC\n",
    "import time\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "%matplotlib inline\n",
    "from matplotlib import pyplot as plt\n",
    "# This is for running the hacked environment\n",
    "import ray\n",
    "ray.init()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Let's play Pacman with a Swarm Wave!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "name = \"MsPacman-ram-v0\"\n",
    "n_walkers = 64 # Size of the swarm, the bigger the better\n",
    "balance = 2  # Balance exploration vs exploitation\n",
    "\n",
    "dt_mean = 4 # Apply the same action n times in average\n",
    "dt_std = 2 # Repeat same action a variable number of times\n",
    "min_dt = 3 # Minimum number of consecutive steps to be taken\n",
    "\n",
    "n_samples = 750000 # Maximum number of samples allowed\n",
    "reward_limit = 23000  # Stop the sampling when this score is reached"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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li3St29fcTgc9YL4rl271O3+lFNOkaefflqGDRsmb775poiIPPHEEy36/SgnOMqJ6RdffKGWUVNTI126dBEAMnXqVHnwwQelU6dOYrfb5b333lOn2759u1qP/X9H//nPfwSAXHfddS1a/m+++UYASFZWVtz71113nRgMBrn88stbfdLq9XqlQ4cOcsIJJ8jmzZvlvPPOEwBxJ3eZmZmNngj1799fotGo/PGPf2x0GrvdLqtWrRIRkX/84x8tOnk47rjjBIC8+OKL6nIbjUa5++675bnnnpOKiooGt/377rtPDAaDAJCTTjpJTjvtNLFYLHLYYYe1+gSDKNkYpOmgpATphsLm2LFj1SAdDofluOOOk9tvvz3u+8rBcNasWep7ZrNZAMhll10mRUVF4nA45KGHHpJRo0aJw+EQEZGsrCx56KGHZO/evXEHgkgkImeddZYAkJUrV0o0GpWuXbvKhRde2ORyKAfsE044Qfbt26e+Hw6H5bXXXpPhw4cLAHniiSdavG5isZh6IJo5c6Zaz/Xr10tOTo7k5uZKYWGhiNS2EAOQa6+9tsXzrysYDMqdd94p/fv3l5kzZ8qgQYMEgGRkZEi/fv2kX79+MmzYMDXIPfjgg/WCtMFgkIqKCrniiiukT58+8tprrwkAWbRoUYvXo2LWrFkCQB566KFWL0tFRYVMnz5djj76aLntttvksMMOU1sLlWUZO3asbNu2rckgHQgEBIBUVVVJNBqVQw89VM4777xW16chjz76qACQ66+/vsHP//Wvf8W1LP/4448CQMaPHy8i/wvSyjx27NghZrNZ/v73v8vQoUMlPz9fRESWLFkiAGT9+vUJ11k58VTmpWxzN998szqNz+dTQ/S1116rBvW6gb2kpESmTZsmAwYMkDvuuEO6du0qAKSgoED9/YwfP15tRZ40aVK9IK1cfbngggvE7/eLiMju3bulV69eYrfb5ZtvvhGR//1dApA//elPccvT0L6jKeFwWLKzs+OCtHJF4YYbbmjxeqzr888/FwDy1FNPiUjtSYjdbpdTTz1VncblconBYJA77rhDdu7cKXv27JF169bJoYceKgBk+fLlMnXqVAEgw4cPl9WrV8uePXtk165dctlllwkAmTBhgojUXq0Daq+SNeX2229Xg3Q4HJacnBy5/PLLm/xORUWFOBwO8Xg8cQ0bO3bskNGjR4vValX3V0RaYJCmg5ISpC+//HI57rjjxGg0qi1XygF03bp1UlhYqLYs7e+SSy4Rp9MpP//8s4jUtjYrB8+srCzp1auXBAIBueeee9Qgfckll8jDDz8cN5/t27fL2LFjZeDAgbJgwQL14N+7d2/5wx/+INu3b5ddu3apL+WyqohIdXW15OTkyF133dXgcq5Zs0YNcy316aefCgB58skn6322fv16cTqdcuutt4pI4kF6f8uWLRMA8vXXXzf4+ahRo9Qg/Ze//EVd39nZ2Wprb1VVlRqkRWrX47HHHtvkelSWDYB07dq1XkttWygBsKEuDPPnz29RkBYR6devnxxzzDGybdu2JuvfnH379onFYhGXyyUlJSUNTvN///d/AkA2b96svjdkyBDJyMiQsrIyCYVC6pUKg8EgmZmZcswxx0gkEpGbbrpJDdKvv/66AJBnn302rs7l5eWtqrPI/65CKCd0Xq9XDj30UOnZs6e6DpSTqilTprS4tfuuu+4Ss9lcr+uGQumuogTpX3/9VaxWa71gLCKyZ88e6dKli4wbN05E4oO01WqVbdu2qdMqQfqZZ55pUT3XrVsX1yK9d+9eMZvN4na7pbS0tEXz2N9tt90mAOK6LY0ZMyYudLpcLjn66KPrfVcJu3WD9A8//BA3jXIlSAnSN998sxqQm3LKKafETde1a1c5+eSTZceOHXHb0f6t/HPnzpWcnJx68ysuLpZDDz1URo0a1YK1QnRgMEjTQUkJ0i+99JJUVFTIgAED5JBDDpFffvlFxo0bpwbpBQsWNNpCuXz5cgEgPXr0EJHaAO5wOKR3795iNpvlq6++EhGR559/Xg3SkydPVoP05s2bZfjw4ZKbmytut1sNTopevXo1eMn0H//4R9x0kydPlqysLAmFQrJmzRp5/PHH5YwzzpChQ4fKUUcdJQDk3HPPbfG6OeOMM2T48OGNBpKrrrpKevbsKSK1gVDp2nHyySfL0KFD5aKLLpJAINDi8upSWkSVk5P9Kf1un3nmGfXS78CBAwWATJ48WURq++wWFBSoQbqx9bj/iUIgEJDhw4eLwWCQLl26yNtvv92mZVDMmzdPADQYeK+44opGL+0rrb5KwFN+h/u/9u/b3ZxYLCYXX3yxGI1Gyc3NlSVLlsT9jmOxmBxzzDFy6KGHSjgcFpHa/uLK7+Tbb78VkdrA5fF4pGfPnmKz2dSuTAsWLFCDtHJVYP9Xp06dJBgMtrjOXq9XCgoKZOjQoep7kUhEPUkpLy+XXbt2icViEavVGtcvtzl1T3AbopwYr169WkRErr32WunZs6faEr2/uXPnisvlkoqKCnn//ffVK0UWi0VOPPFEdV0r+xRlvTVHObHt0KGDiNT+niZMmCBGo1Hy8vLkueeea3WXquHDh0t2drbaJSQajcpnn30mANSuEC6XS2655Za475WUlEhBQYH07dtXotGoTJ06Vbp161ZvO7r00kvFYrGoXTuUv9Hmuln069dPAMjrr78uIqJ2o9n/9cILL8R9b8OGDQ0GaZHaLj1dunRp8z6JKFEM0nRQUoK00qdTaVlVXgUFBeLz+eTCCy+Max2sq7q6WtLT08Vms4mIyGWXXSZHHnmkrFu3Th5//HF1ui1btjQYpJXL33UvASsHpMLCQrHZbHLiiSfK0qVLZdy4cXLRRRfJsmXL6rXGKIH+uuuuE4fDoc7v9NNPl1GjRsmzzz7b4r60yqX8xlqERWpb8gDI3r171Uu2dV9paWmNtng2p6VBuqysTL777jsBIO+//7786U9/kurqanW6s88+WxYtWqT29a67Hi+++GJ54403Gl0ne/fuVbvEXHnllW3qhyzSfJDe/+YxkdowP2fOHAFq+yXv2bNH7Ha7DB48WJYuXSrnn3++TJgwQV5//fU216uqqkomTJggQG3ffSVgBINBASBut1uef/55eeSRR+JuYF2+fLmIiIwbN04GDx4sq1atUrsGiNRe/VCCtNJveu7cuXLHHXfIyJEj5d57741r6W4JpX90ly5d5PXXX5c777wz7sbLDRs2yIYNGwSAzJgxo1XzbkmQ7tSpk8RiMQmFQmI2m+X5559vdPqXX35ZAMinn34q99xzj1itVolEIvLMM88IAPnzn/+shsy2BOmrr7467v3Kykq54IILBICMGTOmVScoaWlpYrFY5Omnn5b58+dLt27d1HWq3MDncrmkQ4cO6g3La9eulaOPPlrMZrN89913IiJqi/TChQslFotJWVmZXHfddQLE36Sq3LT8/vvvN1mvfv36icFgkFAoJFu3bhWTySSnn366PPvsszJ27FiZNGmSLF++vN6JQ1NBevfu3WIymWT79u0tXj9EycQgTQclJUgrB8ZYLCbTp09XDyYDBgwQEZHjjz9eADTYCqUcwE8++WQR+V+Q3t8jjzzSYJCORCJSXl4u5eXl8sYbb4jValX7an/77bcCQN55551mlyUYDNYblWL06NFtWCu162X48OGNfu73+9WbeURqW389Ho84HA5Zvny5lJeXJzRaR1NBOhKJqK3LNTU1apDef/QLn88nZrNZFi1a1Kr1WFcsFpMnn3xSnE6n/P3vf2/TsjQXpHNzc+Waa66RqVOnSm5urqSnp8edCFVWVqqX9ZU+y8n02muvSU5OjtrqqATpuq+uXbuqXRyUoKoE6f3deeedapA+99xzZcCAAa1uKd1f3dEelNfhhx+uBvzHH39cfvjhBwFqb/5rjaaCdGVlpdhsNunevbuIiLzyyivSo0cPtaV+f9FoVCZPnizdu3eXYDAYN+9IJKKG5zFjxki3bt3EZDLJjh07WlRPpZtMY/3aX3nlFcnOzq53H0dT9h8FpmPHjmqf/ksuuUREaoM0UNuFR2mdN5vN8sYbb6jzUYK0cgKmdPuZNGmSut1v27ZNLBaLpKWlNbr+RGr3JV26dBGj0Sgi/zuB+Pjjj5tdno8++qjRIP3DDz8kZVskaiuOI00HpbVr1wKAOj6uwWDAo48+CqvVimXLlmH27NnNzuOpp56C3W7HE0880eR0yljR+zOZTOq4rWPHjsUdd9yBb7/9FgBQWVkJAHA4HM3Ww2q1YuzYsVi6dCluvPFGPPLII9i4cSNWr17d6nFqX331VQwdOrTBz0pKSnDJJZdgy5Yt+OijjwAAFosFNpsNaWlpOOecc1pVVmvt3Lmz3hjKDYlEIohEIgBatx7rMhgMmDp1KjZv3qyOsZzsMXaLi4vx888/49hjj8XVV1+NgQMHonfv3njuuedw3333wWAwtLn+LTFu3DgUFhZixowZuPTSS9G9e3cAQPfu3TFx4kSceeaZOPbYY7Fv3z707NkT69evb3J+dbfzyspKOBwOGAyGpNR1wIABGD16NMaOHYt+/frh66+/xuDBg7F+/XpMmzYN/fv3x8svv4zp06ejb9++cd+tqqqCyWRqcJz2xnzyyScIBoPqz6+++ip69OgBs7n+IbGmpgazZs3Cq6++infeeQdWqzXuc5PJhKeffhrV1dVYtmwZgNqxy7t27dqiurz77rtNfj5+/HgUFhZi5syZmDx5Mnr27Nmi+RYUFOCKK67A0KFDccIJJ8Dv96NHjx7YsGFD3HSdO3fGJZdcArPZjJNPPrnB8dRtNhvGjx+Pzp07Izs7G9dee606zvf27dsRDocBAJs3b0afPn0arM+mTZuwc+dOGI21D1Ruzbb/3nvvNfrZ66+/jry8vKRti0StxSBNB6V169YBiN9JGwwGPPTQQ3jooYfU95QHRgQCgbiHCHz++ef429/+hmuuuabegbs5IhL3s9frxb/+9S+89tprOPfccwEAb7/9NgDg+uuvx4gRI/D555/HfeeRRx7BCSecoP48evRoLF26FNOmTcORRx6JKVOmYOjQoVi5cmXcdM0JBALYuHGjurx+vx8VFRWYN28eFixYgIyMDHz00Ufo1atXq5Y5GVauXAmg9mEzjT2MY3+tXY/7MxqNCIVC2LhxY6vWY0tcf/31+Nvf/lbv/UMOOUT9v1L/GTNmYNSoUfjss8/ipn3ggQdw8sknt7kORqMRIoK1a9eqQfqGG27A9ddfr07TpUsXdO7cGd9//32L5unz+fDhhx/CarXimmuuQWFhIUpKStTPDz/8cCxZsqRV9bznnnswcuRI9edBgwbBbDbj+++/h8lkwn333YdzzjkHV199NZYvX47MzEwAtQ+Kufjii3H++edj1qxZLS5P2daU/UMgEMC2bdtQXl6OzMxMhEIheL1eLFq0CHPnzoXf78c777zT6EmoyWTCo48+im+//Ra//vorbrnlljbXpSHK73HdunUtDtJTp07F3Xffrf7scDhwxBFHYNWqVep7eXl5+Omnn5oNs6+99hpGjRrV4GfKPjQcDuOEE06oF6QtFguWL19ebzmVbX/atGk49dRT8dVXX8V9b/78+TjmmGMAAKeffjoWLVpUr2wRwWuvvYaHH364yfoTHUgM0nRQuv7661FaWoozzzyzyenGjx+PTz75BPPnz8ftt98OoPbgPHHiRHTr1g0PPPCAOu1JJ52Eb775pt48zGYzevToof78j3/8A1988QWA2tbTlStXwmw246abbsJf/vIXAFBbZTZs2KC2EPXs2RNHHXUUDjvsMBx77LFxZRQWFsLj8SAzMxOTJ08GAEyZMgVnnnlmq8L0n/70J0ybNg3du3fHoEGD8N577yEUCuHQQw/FM888g3POOadei1sybd++vdHPiouLAQBnnXUW7HY7Dj/8cOTl5dWbzmQywWQyoXv37vjpp58ANLwee/bsqT4RMBwO4+2330bnzp1htVqxdetWfPvtt3jooYcwcuTINj05sKllAWpbBBtSt9VT2Q42btyIjRs3AgAOO+ww9OvXD927d2/x71VE8PbbbyM9PR0FBQVYv349fv75Z9xyyy047rjjMHLkSOzYsQMAcNppp9X7/vnnn4+nn34aQO12/s9//rPBevfo0UNt+QuFQliwYAGA2pPUs88+G3a7HVdddVWL6gzUrkObzYbBgwfXK+vcc89V6zxy5Eg89dRTuPLKK9GtWzeMGTMGvXv3xrx58xCJRNS/ibqU7zZE2dbGjBkDAJg+fTqGDRuGbt264dRTT8Vnn32GiooKZGZm4tFHH8WYMWOavWLRtWtXfPnll9i5c2ertqe6dVF+jxkZGcjLy8OGDRuwdetW3HrrrRg8eDBGjBjR7PyKiorg8/ka/D2PHz8+LkiPGTOm2RCdm5vb4LwUxx9/PG688UY8/PDDqKysVANxjx490K9fP2zduhUbNmyot86VbX/NmjVYs2YNAKB3797o3bs3+vTpE/dEw8b+lpSnKA4bNqzJZSA6kBik6aB07bXXtmi6KVOmYMGCBZg7d6564F2xYgWqq6uxcuXKuMcPn3POOcjNza03j5tuugk33ngjAODqq6/GkCFDsGHDBmzatAljxozB6NGjccwxx8R1w5g1axYGDhyIUaNGqa2vNptNPbjsr7q6Gvfff796MK8bpseOHYtt27a16NL21VdfjWOPPRYPPvggRATz58/H2WefjYKCgkZbgadMmdKqR/42ZfPmzejWrRs6duzY6DRKC5fT6cRTTz2F/v37x33udDrh9/thsVhw5JFHtmg9VlVVYeLEiWr3hP79+yM/Px/vvPMORowY0abLwps3b8Zxxx3X6O+sMePGjcPOnTvhcrkwY8YMHHXUURg1apQasJvaDhojIrjssstQWloKAOjVqxc6dOiAF154AePHj4fJZFJP7rp06VLv+1deeSU++OADAMAFF1zQ4BUJpXXTZDLh3XffRUFBAQ4//HAAtaGoNY8DV3zxxRdwuVzIysqq99m0adPw2GOPqT9ffvnlOPXUU3H//ffjp59+wo4dO3DGGWfg9ttvb/CE66effsKQIUOaLF+p8+mnn46tW7fi/vvvx65duzBnzhwMHToUPXr0gMViafHydOzYscltu7m6xGIxTJkyBWVlZQBqg2VBQQFefPFFnH/+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Wxmtg7Tdqs+uHczRREREpDftEqSfeOIJvPzyyxgyZAjOPfdcfPfddxg2bBi++uorZGZmqtPNnz8fCxcuVH8+6aSTMGTIEAC1Ibs1QVqrrh0Oiz6DNBEREZHeJCN3Nhmko9EoFixYgLvvvhs33HCD+t7JJ5+MBx98EA888IA67erVq9GzZ098+OGHyM3Nhc1ma3S+s2fPxl133RX33ujRo/H8888DAEpLS9u8QIlw63TUDqNB6xoQERERta+srCwAieXOJvtIf/fdd9i1axcmT56svmcymdClS5d6Qbm6uhperxfPP/88Pv30U4i0rr/A7t274fF44Ha7sXv37lZ9N1nSdHqzodmYUvecEhERER1wycidTSaoTZs2oVOnTmpiB4CtW7di5cqVGDduXNy048ePx+7du3HLLbdg+PDhmDx5cqvG5SsuLgYAZGdno6ysrDXLkDR67dphNrFJmoiIiPQn0dzZbFNkMBhUW5fLy8sxYcIEXHnllejXrx9KS0vx2WefAQDuvvtufPjhh3jppZcwb948rFy5EpdcckmD85w9ezZEJO61fft2ALXN7CUlJW1eoERYzUa4dHjDocXEFmkiIiLSn0RzZ5Odgk8++WQUFhZiypQpOPzww7FkyRJMmDABs2fPBgBce+21eOutt1BTUwODwYChQ4eq3/3kk0+wZcuWVleooKAAe/fubfX3kiXDaYU35NesfC1YzQzSREREpD+J5s4mE1S3bt3wn//8B5s2bcLLL7+Mxx57DPfccw9MptpW25tuuglffvllve+VlpZi7dq1yM7ObnWFCgoKNOsjDQA2i/5CpZUt0kRERKRDiebOZoepOOWUU7Bq1SqICIz73ZQ2YMAAALX9ppX/H3bYYdi+fTsCgQCWLFnS6gp16NABRUVFiMVi9cprDx67/m44ZB9pIiIi0qNEc2eLvmEwGJqceY8ePbBixQpMmzYNZrMZvXv3xsqVK3HSSSe1ukIFBQWIxWIoKipq9XeTIc2uvyHw9HqTJREREelborkzKanRYDDgxBNPxIknnpjwvDp06AAAKCoqQkFBQcLzay09hkq9DvtHRERE+pZo7ky5zrFKv2qtHsri1OGoHRkM0kRERKRDiebOlAvS6enpAICqqipNys9wWjUpV0tskSYiIiI9SjR3plyQdjqdAACv16tJ+XlpjT/a/GCVziBNRERE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OgMAXvz6V6wtrGzRd2ICQARRCELRGBLtUu6ympDltiLbZUOO24ZcjxVumxlumwVuuxkemxlpjtpQ7rCaYDEaYbMY4bCYYDMbYTObYLcaYTEaYTD87ymNsVjtCUBMam+mjMRiiMYE4aggGInCajYiz6PNI+iJiIgodSSaO9sUpLds2YJDDjkEFoul0Wmqq6tRWFiII444AkZjy7sPVFRUwGazafKIcJ+OnmqYZq/93W3Y1bIQfSB4Q1F4y/zYWeZv13LfveEkBmkiIiJKOHe2qoPs+vXrceqpp+Lwww/HkUceia1btzY43Q8//IDjjjsOffr0wRNPPNGqClVVVWk2hrQ3qJ8WaaUbix5vNgyGOVIJERERJZ47WxykvV4vTjvtNKxatQo9e/bEiBEj0LdvX2zevDluug8++ACDBg2C0+lEt27d8N5777WqQiUlJcjKymrVd5Kl0q+fh7HU/HbS4NRhP2U9deEhIiKixiWaO1scpF9//XW4XC5UVlbi22+/xbx58zBjxgyMHj06brrZs2fjggsuwDfffIPRo0er/Vb3n8ZgMNR7RaNRlJWVITs7u80LlIgqHQVp/29h0mFNuW7yB1xARzeVEhERUeMSzZ0tDtJPPvkkrrjiClitVvV55KeddhpKSkripnvrrbewYMECFBcXY/ny5bjgggtaNH+bzQaTyQSv16vJ0HcA4A/rJ2D5w7X9wfXYtcMb1E9feCIiImpcormzxUH6q6++wrBhw+LeW758OUaOHBn3XkZGBpxOJ2699Vb07t0bEydObNH8lXBeU1MDt9vd0molVU1APwFL6Q/useuvRdqno77wRERE1LhEc2ebn8bx1ltv4dlnn8WcOXMAAHv27FE/+/7777Fs2TL83//9X4PfnT17NkQk7lVcXAygdjw/9pE+8Mp9IQBAprPxkVcOVuzaQUREREDiubPFQbpv37544IEH8PHHH+O+++7D9OnTsWzZMnTq1Al79+5Fp06d8Mknn0BEcMcdd2DEiBE499xzW12hiooKzYJ0tY4u+ZfW1AbpXB0OAxfQURceIiIialyiubPFQXrp0qXYsWMHhg4dik8++QRffvml2tXDZrPhqquuwuDBg/HMM8/grbfewhdffIGJEydi4sSJeP/991tURjgcRiAQULt5tLegjgLWvqoAACDXY9O4Ju0vwOHviIiIdC8ZubPF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DoexaNEiRKPRbkfWe+r+++/HjBkzUFVVBU3TsHr1aqxduxa33HILlixZgrlz5+LJJ580RoK/+eYbvPTSS7j00kv3+dqbN29GJBIBUBjl3rZtG7xeb8lz3njjDSxatAhVVVW45557dnuNxYsXY9OmTXj22Wdx/PHHU5AmhFQECtKEkINWQ0MDRo4ciVNOOcV4zOv19ij8AYDdbkd1dTVqamqwatUqTJs2DbNmzQJQGFVmjKG5uRnNzc14+umnjdf3er1YtmyZEaRlWcZtt922x3WSt23bBgDGHGWLxYLa2lqMHTsWp59+OoDCiO748eMxbNgw4/tOOeUU6LoORVFKXi+dTvfos3GZTAaSJGHy5MnGUoA2mw3jxo1DOp1GdXU1Vq5ciXPOOQdnn3025syZA0VRMHfuXPz617/e7bX25P333wdQmDs+ePBgDBs2DFOnTsUll1yCd955B59//jmSySQuvvhiY8rMnixfvhxDhw7t8c+PEEL2NwrShJCD1uTJk0s2ROmtWCyGUCiEc845B263uyRMNzY2YsyYMbj//vtxxBFHGCF09OjRuwXBUCi0181GLrzwQtTX12PMmDEAgNraWhxxxBElz1m7di2uvPLKkseOO+44jB07tuS9NE3Dhx9+iPnz5/f4M65btw7BYNCYMsFdcsklePXVVwEAU6ZMQVNTE2655RbccMMNAIBLL70U1157bcn3NDU1oba2dq9TQOrr6+FwOPDmm2/i1ltvxfLlyzFhwgRccsklOOGEE3Ybpf4uj8djTIkhhJBKQBuyEEJIL+TzeSxduhTHHnssTjvttH0+/91338VVV11lbLjSF2+++SYaGhp2C9iapu02zzsajaKqqmqf8625dDqN//u//8P555+/2//t6fW7wxhDNBpFTU1NyeN//vOfsXz5cjzwwAO9mmc9YsQI3HfffZgwYUKPv4cQQgYSBWlCCNnPGGO0ykQftLS0oK6urldhnhBCBhIFaUIIIYQQQvqgZ9f+CCGEEEIIISUoSBNCCCGEENIHFKQJIYQQQgjpAwrShBBCCCGE9AEFaUIIIYQQQvrg/wONZJLAUNACswAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 864x360 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "abs_rnd = np.abs(np.random.normal(loc=dt_mean, scale=dt_std, size=100000))\n",
    "dt = np.maximum(min_dt, abs_rnd).astype(int)\n",
    "with plt.xkcd():\n",
    "    plt.figure(figsize=(12,5))\n",
    "    _ = plt.hist(dt, density=True)\n",
    "    plt.title(\"Number of times the same action is applied\")\n",
    "    #plt.grid()\n",
    "    _ = plt.xlabel(\"N repeat action\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "save_data = True # Save the data generated\n",
    "prune_tree = True\n",
    "skip_frames = 0  # Number of frames to skip at the beginning\n",
    "render_every = 10  # print statistics every n iterations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/lib/python3.6/dist-packages/gym/__init__.py:22: UserWarning: DEPRECATION WARNING: to improve load times, gym no longer automatically loads gym.spaces. Please run \"import gym.spaces\" to load gym.spaces on your own. This warning will turn into an error in a future version of gym.\n",
      "  warnings.warn('DEPRECATION WARNING: to improve load times, gym no longer automatically loads gym.spaces. Please run \"import gym.spaces\" to load gym.spaces on your own. This warning will turn into an error in a future version of gym.')\n"
     ]
    }
   ],
   "source": [
    "env = ParallelEnvironment(name=name,env_class=AtariEnvironment,\n",
    "                          blocking=False, n_workers=8)  # We will play an Atari game\n",
    "model = RandomDiscreteModel(n_actions=env.n_actions) # The Agent will take discrete actions at random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "sw = SwarmWave(model=model, env=env, n_walkers=n_walkers, reward_limit=reward_limit, samples_limit=n_samples,\n",
    "                  render_every=render_every, balance=balance, save_data=save_data,\n",
    "                  dt_mean=dt_mean, dt_std=dt_std, accumulate_rewards=True, min_dt=min_dt,\n",
    "                  prune_tree=prune_tree, can_win=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Environment: MsPacman-ram-v0 | Walkers: 64 | Deaths: 0 | data_size 105\n",
      "Total samples: 354339 Progress: 101.18%\n",
      "Reward: mean 22897.41 | Dispersion: 400.00 | max 23271.00 | min 22871.00 | std 68.11\n",
      "Episode length: mean 5806.91 | Dispersion 14.00 | max 5814.00 | min 5800.00 | std 3.06\n",
      "Dt: mean 4.03 | Dispersion: 6.00 | max 9.00 | min 3.00 | std 1.37\n",
      "Status: Score limit reached.\n",
      "Efficiency 0.47%\n",
      "Generated 1649 Examples | 214.88 samples per example.\n",
      "\n",
      "CPU times: user 7.68 s, sys: 231 ms, total: 7.91 s\n",
      "Wall time: 45.4 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "sw.run_swarm(print_swarm=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "unexpected EOF while parsing (<ipython-input-8-8cce414f068d>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  File \u001b[0;32m\"<ipython-input-8-8cce414f068d>\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m    @Miau_db # Dirty trick to stop after clicking on Run All\u001b[0m\n\u001b[0m                                                            ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m unexpected EOF while parsing\n"
     ]
    }
   ],
   "source": [
    "@Miau_db # Dirty trick to stop after clicking on Run All"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "sw.render_game(sleep=0.01)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Statistics about the data generated"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Copy paste from cell above\n",
    "total_saples = sw._n_samples_done\n",
    "mean_samples = sw.times.mean() # Mean episode length\n",
    "score = sw.rewards.max()\n",
    "time = 35\n",
    "\n",
    "score_human = 15693\n",
    "fps_atari = 20\n",
    "\n",
    "mean_fps_fai = (mean_samples / time) \n",
    "mean_fps_rel = mean_fps_fai/ fps_atari\n",
    "\n",
    "samples_action = total_saples / mean_samples\n",
    "score_ratio = score / score_human \n",
    "\n",
    "print(\"The game was sampled after {} samples, at {:.2f} fps, \\n\"\n",
    "      \"{:.2f} times faster than human gameplay. \\n\"\n",
    "      \"It achieved an score {:.2f} times better than a human playing for 2 hours.\\n\"\n",
    "      \"It took {:.2f} samples per frame (per game on average).\\n\"\n",
    "      .format(total_saples, mean_fps_fai, mean_fps_rel, score_ratio, samples_action))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Benchmark against other planning algorithms: UCT & p-IW"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- [Planning with Pixels in (Almost) Real Time](https://arxiv.org/pdf/1801.03354.pdf)\n",
    "- [Blind Search for Atari-Like Online Planning Revisited](https://www.ijcai.org/Proceedings/16/Papers/460.pdf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "N_cluster = 2\n",
    "cluster_coef =  (64 * 2.3) / (8 * 2.8) # 64 cpus @2.3GHz M4.16xlarge vs. 8cpus @2.8GHz my laptop\n",
    "plan_samples_action = 150000\n",
    "ipw_score = 30785\n",
    "\n",
    "samples_ratio = plan_samples_action / samples_action\n",
    "ipw_score_ratio = score / ipw_score\n",
    "\n",
    "ipw_fast_score = 15115.0\n",
    "ipw_fast_fps = 0.5\n",
    "ipw_fast_faster =  mean_fps_fai / ipw_fast_fps\n",
    "ipw_fast_samples_ratio = mean_fps_fai / ipw_fast_fps * cluster_coef * N_cluster\n",
    "ipw_fast_score_ratio = score / ipw_fast_score \n",
    "\n",
    "big_ipw_score = 23033.0\n",
    "big_ipw_fps = 1 / 32\n",
    "big_ipw_faster = mean_fps_fai / big_ipw_fps\n",
    "big_ipw_samples_ratio = mean_fps_fai / big_ipw_fps * cluster_coef * N_cluster\n",
    "big_ipw_score_ratio = score / big_ipw_score \n",
    "\n",
    "uct_score = 22336\n",
    "uct_score_ratio = score / uct_score \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "print(\"Efficientcy vs.p-IW at 0.5fps in a cluster:\\n\"\n",
    "      \"It a chieved and score {:.2f} times better than p-IW.\\n\"\n",
    "      \"SW is {:.2f} times faster than p-IW on a cluster of M4.16xlarge running at 0.5fps.\\n\"\n",
    "      \"SW is {:.2f} times more efficient than p-IW.\\n\"\n",
    "      .format(ipw_fast_score_ratio, ipw_fast_faster, ipw_fast_samples_ratio))\n",
    "\n",
    "print(\"Efficientcy vs. p-IW 1/32fps in a cluster:\\n\"\n",
    "      \"It a chieved and score {:.2f} times better than p-IW.\\n\"\n",
    "      \"SW is {:.2f} times faster than p-IW on a cluster of M4.16xlarge running at 1/32 fps\\n\"\n",
    "      \"SW is {:.2f} times more efficient than p-IW.\\n\"\n",
    "      .format(big_ipw_score_ratio, big_ipw_faster, big_ipw_samples_ratio))\n",
    "\n",
    "print(\"Efficiency vs. 150k p-IW:\\n\"\n",
    "      \"It a chieved and score {:.2f} times better than p-IW.\\n\"\n",
    "      \"SW is {:.2f} times more efficient than p-IW.\\n\"\n",
    "      .format(ipw_score_ratio, samples_ratio))\n",
    "\n",
    "print(\"Efficiency vs. 150k UCT:\\n\"\n",
    "      \"It a chieved and score {:.2f} times better than UCT.\\n\"\n",
    "      \"SW is {:.2f} times more efficient than UCT.\\n\"\n",
    "      .format(uct_score_ratio, samples_ratio))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "columns = [\"FPS\", \"Samples/action\", \"Score\"]\n",
    "index = [\"Swarm Wave\", \"Human\", \"UTC (AlphaZero)\",\"p-IW 150k\", \"p-IW cluster 0.5s\", \"p-IW cluster 32s\"]\n",
    "data = [[mean_fps_fai, samples_action, score],\n",
    "        [fps_atari, np.nan, score_human],\n",
    "        [np.nan, plan_samples_action, uct_score],\n",
    "       [np.nan, plan_samples_action, ipw_score],\n",
    "       [ipw_fast_fps, np.nan, ipw_fast_score],\n",
    "       [big_ipw_fps, np.nan, big_ipw_score]]\n",
    "results = pd.DataFrame(index=index, columns=columns, data=data)\n",
    "results[\"Times faster\"] = results.loc[\"Swarm Wave\",\"FPS\"] / results.loc[:, \"FPS\"]\n",
    "uct_piw = [\"UTC (AlphaZero)\", \"p-IW 150k\"]\n",
    "results.loc[uct_piw, \"Times faster\"] = results.loc[uct_piw,\n",
    "                                                   \"Samples/action\"] / results.loc[\"Swarm Wave\",\n",
    "                                                                                   \"Samples/action\"]\n",
    "results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with plt.xkcd():\n",
    "    _ = (100 * results[\"Score\"] / results[\"Score\"][0]).plot(kind=\"bar\",\n",
    "                                                            title=\"% Score achieved vs SW\",\n",
    "                                                            figsize=(12,5))\n",
    "    plt.ylabel(\"Score pct vs. SW\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "with plt.xkcd():\n",
    "    _ = np.log10(results[\"Times faster\"]).plot(kind=\"bar\", title=\"How many orders of magnitude faster a Swarm Wave is\",\n",
    "                                               figsize=(12,5))\n",
    "    plt.ylabel(\"Times faster\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Let's try FMC"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "name = \"MsPacman-ram-v0\"\n",
    "skip_frames = 0  # Number of frames to skip at the beginning\n",
    "dt_mean = 5 # Apply the same action n times in average\n",
    "dt_std = 2 # Repeat same action a variable number of times\n",
    "min_dt = 4 # Minimum number of consecutive steps to be taken\n",
    "n_samples = 2500 # Maximum number of samples allowed\n",
    "reward_limit = 100000  # Stop the sampling when this score is reached\n",
    "n_walkers = 60 # Maximum witdh of the tree containing al the trajectories\n",
    "render_every = 1  # print statistics every n iterations.\n",
    "balance = 2  # Balance exploration vs exploitation\n",
    "time_horizon = 40 # How deep we want each cone to be on average\n",
    "min_horizon = 30 # Minimum time horizon for the cone\n",
    "clone_seeds = False # Clone random seeds when getting ale state. If false env is stochastic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "fmc_env = ParallelEnvironment(name=name, env_class=AtariEnvironment, clone_seeds=clone_seeds,\n",
    "                          blocking=False, n_workers=8)  # We will play an Atari game\n",
    "fmc_model = RandomDiscreteModel(n_actions=fmc_env.n_actions) # The Agent will take discrete actions at random"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fmc = FractalMC(model=fmc_model, env=fmc_env, max_walkers=n_walkers,\n",
    "                reward_limit=reward_limit, max_samples=n_samples,\n",
    "                render_every=render_every, balance=balance, time_horizon=time_horizon,\n",
    "                min_horizon=min_horizon, dt_mean=dt_mean, dt_std=dt_std, accumulate_rewards=True,\n",
    "                min_dt=min_dt, can_win=False, update_parameters=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "fmc.run_agent(print_swarm=False, render=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Q-bert as a proof of concept"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### - Create a super-human gym-like Env\n",
    "### - Sample games uring [ray](https://ray.readthedocs.io/en/latest/)\n",
    "### - True action inside info\n",
    "### - Hack OpenAI [baselines](https://github.com/openai/baselines)!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Parameters for the swarm used in the hacked Env"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fractalai.model import RandomDiscreteModel\n",
    "from fractalai.environment import ParallelEnvironment, AtariEnvironment\n",
    "from fractalai.swarm_wave import SwarmWave\n",
    "from fractalai.fractalmc import FractalMC\n",
    "import time\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "%matplotlib inline\n",
    "from matplotlib import pyplot as plt\n",
    "# This is for running the hacked environment\n",
    "import ray\n",
    "ray.init()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "swarm_kwargs = dict(dt_mean=10,  # Apply the same action n times in average\n",
    "                    dt_std=5,  # Repeat same action a variable number of times\n",
    "                    min_dt=5,  # Minimum number of consecutive steps to be taken\n",
    "                    samples_limit=3000000,  # 200000  # Maximum number of samples allowed\n",
    "                    reward_limit=35000,  # Stop the sampling when this score is reached\n",
    "                    n_walkers=150,  # Maximum width of the tree containing al the trajectories\n",
    "                    render_every=100,  # print statistics every n iterations.\n",
    "                    balance=2,  # Balance exploration vs exploitation\n",
    "                    save_data=True,  # Save the data generated\n",
    "                    accumulate_rewards=True,\n",
    "                    prune_tree=True)\n",
    "\n",
    "generator_kwargs = {}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Same interface as OpenAI baselines"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# requires OpenAI baslines\n",
    "from fractalai.datasets.baselines import make_atari_env\n",
    "\n",
    "env_id = \"QbertNoFrameskip-v4\"\n",
    "num_env = 2\n",
    "seed = 10\n",
    "n_actors = 8\n",
    "hacked_env = make_atari_env(env_id, num_env, seed, wrapper_kwargs=None, start_index=0, swarm_kwargs=swarm_kwargs,\n",
    "                           generator_kwargs=generator_kwargs, n_actors=n_actors, mode=\"load\", folder=\"game_data\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Fill up the buffer of played games"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time \n",
    "obs = hacked_env.reset()\n",
    "print(len(obs))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Let's see how it plays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%time\n",
    "import time\n",
    "\n",
    "for i in range(3):\n",
    "    ends = [False, False]\n",
    "    while not ends[0]:\n",
    "        observation, rewards, ends, infos = hacked_env.step(\"IGNORE THIS\")\n",
    "        hacked_env.render()\n",
    "        time.sleep(0.005)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Dataset generation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fractalai.datasets.mlswarm import MLWave, MLFMC\n",
    "from fractalai.datasets.data_generator import DataGenerator "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "name = \"MsPacman-v0\"\n",
    "skip_frames = 0  # Number of frames to skip at the beginning\n",
    "dt_mean = 5  # Apply the same action n times in average\n",
    "dt_std = 2.5 # Repeat same action a variable number of times\n",
    "min_dt = 3 # Minimum number of consecutive steps to be taken\n",
    "n_samples = 100000#200000  # Maximum number of samples allowed\n",
    "reward_limit = 10000  # Stop the sampling when this score is reached\n",
    "n_walkers = 75  # Maximum witdh of the tree containing al the trajectories\n",
    "render_every = 1  # print statistics every n iterations.\n",
    "balance = 2  # Balance exploration vs exploitation\n",
    "save_data = True # Save the data generated\n",
    "\n",
    "prune_tree = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sw = MLWave(model=model, env=env, n_walkers=n_walkers, reward_limit=reward_limit, samples_limit=n_samples,\n",
    "                  render_every=render_every, balance=balance, save_data=save_data,\n",
    "                  dt_mean=dt_mean, dt_std=dt_std, accumulate_rewards=True, min_dt=min_dt,\n",
    "                  prune_tree=prune_tree)\n",
    "datagen = DataGenerator(sw)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Save whole games into a folder"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%time\n",
    "n_games = 1\n",
    "output_folder = \"dataset\"\n",
    "for i in range(n_games):\n",
    "    datagen.save_run(output_folder, print_swarm=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generate examples for supervised learning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "example_gen = datagen.example_generator()\n",
    "obs, action, reward, next_obs, end = next(example_gen)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generate batches of examples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "batch_gen = datagen.batch_generator()\n",
    "obs, action, reward, next_obs, end = next(batch_gen)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "len(reward)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
